import requests
import time
import base64
from requests.exceptions import RequestException
from lxml import etree
from bs4 import BeautifulSoup
from pyquery import PyQuery
import json
import re
from io import BytesIO
from fontTools.ttLib import TTFont


def get_page_show_ret(string, bs64_str):
    '''解密字体信息'''
    font = TTFont(BytesIO(base64.decodebytes(bs64_str.encode())))
    c = font['cmap'].tables[0].ttFont.tables['cmap'].tables[0].cmap
    ret_list = []
    for char in string:
        decode_num = ord(char)
        if decode_num in c:
            num = c[decode_num]
            num = int(num[-2:]) - 1
            ret_list.append(num)
        else:
            ret_list.append(char)
    ret_str_show = ''
    for num in ret_list:
        ret_str_show += str(num)
    return ret_str_show


def getPage(url):
    '''爬取指定url地址的信息'''
    try:
        # 定义请求头信息
        headers = {
            'User-Agent': 'User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/70.0.3538.110 Safari/537.36'}
        # 执行爬取
        res = requests.get(url, headers=headers)

        # 判断并返回结果
        if res.status_code == 200:
            return res.text
        else:
            return None
    except RequestException:
        return None


def parsePage(content, keyword=1):
    '''解析爬取网页中的内容，并返回字段结果'''
    # 定义正则表达式
    pat = "charset=utf-8;base64,(.*?)'\) format"
    # 执行正则解析获取base64字符串
    bs64_str = re.findall(pat, content)[0]

    if keyword == 2:
        # ===============使用BeautifulSoup=======================

        # 初始化，返回使用BeautifulSoup对象
        html = BeautifulSoup(content, 'lxml')
        # 解析网页中<ul class='listUl'>...</div>中有sortid属性的li标签信息（每间租房的信息）
        items = html.select("ul.listUl li[sortid]")
        # 遍历并解析每间租房的具体信息
        for item in items:
            yield {
                '标题': get_page_show_ret(item.select("div.des h2 a.strongbox")[0].get_text().strip(), bs64_str),
                '图片': "http:" + item.select('div.img_list img')[0].attrs['lazy_src'],
                '户型': get_page_show_ret(item.select('div.des p.room.strongbox')[0].get_text().strip(),
                                        bs64_str).replace("\xa0\xa0\xa0\xa0", '|').replace(" ", ""),
                '价格': get_page_show_ret(item.select('div.listliright div.money b.strongbox')[0].get_text().strip(),
                                        bs64_str),
            }
    elif keyword == 3:
        # ===============使用PyQuery=======================

        # 初始化，返回PyQuery对象
        doc = PyQuery(content)
        # 解析网页中<ul class='listUl'>...</div>中有sortid属性的li标签信息（每间租房的信息）
        items = doc("ul.listUl li[sortid]")
        # 遍历并解析每间租房的具体信息

        for item in items.items():
            yield {
                '标题': get_page_show_ret(item.find('div.des h2 a.strongbox').text(), bs64_str),
                '图片': "http:" + item.find('div.img_list img').attr('lazy_src'),
                '户型': get_page_show_ret(item.find('div.des p.room.strongbox').text(), bs64_str).replace(
                    "\xa0\xa0\xa0\xa0",
                    '|'),
                '价格': get_page_show_ret(item.find('div.listliright div.money b.strongbox').text(), bs64_str),
            }
    else:
        # ===============使用xpath=======================
        # 初始化，返回根节点对象
        html = etree.HTML(content)
        # 解析网页中<ul class='listUl'>...</div>中有sortid属性的li标签信息（每间租房的信息）
        items = html.xpath("//ul[@class='listUl']/li[@sortid]")
        # 遍历并解析每间租房的具体信息
        for item in items:
            yield {
                '标题': get_page_show_ret(item.xpath(".//div[@class='des']/h2/a[@class='strongbox']/text()")[0].strip(),
                                        bs64_str),
                '图片': "http:" + item.xpath('.//div[@class="img_list"]/a/img/@lazy_src')[0],
                '户型': get_page_show_ret(item.xpath(".//div[@class='des']/p[@class='room strongbox']/text()")[0].strip(),
                                        bs64_str).replace("\xa0\xa0\xa0\xa0", '|').replace(" ", ""),
                '价格': get_page_show_ret(
                    item.xpath(".//div[@class='listliright']/div[@class='money']/b/text()")[0].strip(),
                    bs64_str),
            }


def writeFile(content):
    '''执行文件追加写操作'''
    with open("./result.txt", 'a', encoding='utf-8') as f:
        f.write(json.dumps(content, ensure_ascii=False) + '\n')


def main(keyword, offset):
    '''主程序函数，负责调度执行爬虫处理'''
    url = "http://bj.58.com/dashanzi/chuzu/pn" + str(offset) + "/?ClickID=1"
    # print(url)
    html = getPage(url)  # 执行爬取
    # print(html)
    if html:
        for item in parsePage(html, keyword):  # 执行解析并遍历
            print(item)


if __name__ == '__main__':
    # main(0)
    keyword = int(input('请选择解析方式（xpath(默认):1 ,BeautifulSoup:2 ,PyQuery:3）：'))
    for i in range(1, 3):
        print("=" * 20, '第%d页' % i, "=" * 20)
        main(keyword, offset=i)
        time.sleep(1)
    print("=" * 60)
    print('爬取结束，这里只爬取2页，需要的更多的数据可自行修改数值')
